//@Author: cyl
//@File: main.go
//@Time: 2023/06/14 22:08:18
package main

import (
	"fmt"
	"sort"
)

/**
排序
type Interface interface {
	Len() int 			// 获取数据集合的个数
	Less(i, j int) bool // 如果i索引的数据 < j索引元素的数据, 返回true调用下面的Swap(), 即数据升序排序; 返回false则不调用
	Swap(i, j int) 		// 交换i和j索引的两个元素位置
}
1、sort包的底层实现是多种排序的算法，例如快排，插入等等；调用时并不公开，也无需定义用那种算法
2、sort包内部会根据实际情况，自动选择最高效的排序算法
*/
// 定义序列类型，只要此类型实现了sort.interface{}接口(实现三要素方法)，就可以对此类型排序
type TestStringList []string

// 元素个数
func (t TestStringList) Len() int {
	return len(t)
}

// 比较结果
func (t TestStringList) Less(i, j int) bool {
	return t[i] < t[j]
}

// 交换方式
func (t TestStringList) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
}

func SortPackageDemo() {
	// 1、Sort
	stringList := TestStringList{
		"1-php",
		"2-java",
		"3-golang",
		"4-c",
		"5-cpp",
		"6-python",
	}

	//按照定义的规则排序
	sort.Sort(stringList)
	fmt.Println(stringList) // [1-php 2-java 3-golang 4-c 5-cpp 6-python]

	//按照定义的规则反向排序
	sort.Sort(sort.Reverse(stringList))
	fmt.Println(stringList) // [6-python 5-cpp 4-c 3-golang 2-java 1-php]
}

func demoSortSlice1() {
	// 2、Slice
	/**
	概览：
		Go 1.8之后的版本，Go语言在 sort 包中提供了 sort.Slice() 函数进行更为简便的排序方法。
		sort.Slice() 函数只要求传入需要排序的数据，以及一个排序时对元素的回调函数

	实现：
		sort.Slice(tmp,func(i,j int){
			return tmp[i]<tmp[j]
		})
	*/
	a := []int{6, 3, 9, 8, 1, 2, 5, 7}
	sort.Slice(a, func(i, j int) bool {
		return a[i] > a[j]
	})
	fmt.Println(a) // [9 8 7 6 5 3 2 1]
}

func demoSortSlice2() {
	type sortUser struct {
		Id   int
		Name string
		Age  int
	}
	list := []sortUser{
		{Id: 10, Name: "nick", Age: 100},
		{Id: 7, Name: "nick", Age: 210},
		{Id: 9, Name: "nick", Age: 90},
		{Id: 12, Name: "nick", Age: 1},
		{Id: 21, Name: "nick", Age: 28},
		{Id: 17, Name: "nick", Age: 300},
	}
	sort.Slice(list, func(i, j int) bool {
		return list[i].Age < list[j].Age
	})
	fmt.Println("list:", list) // [{12 nick 1} {21 nick 28} {9 nick 90} {10 nick 100} {7 nick 210} {17 nick 300}]
}

func main() {
	SortPackageDemo()
	demoSortSlice1()
	demoSortSlice2()
}
